/**
 * Copyright (C) 2008 aileron.cc
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package cc.aileron.commons.utility;

import java.io.Closeable;
import java.io.IOException;

/**
 * stream-utils
 * 
 * @author Aileron
 * 
 */
public class StreamUtils
{   
    /**
     * 
     * @author Aileron
     *
     * @param <STREAM>
     * @param <T>
     */
    public static abstract class using<STREAM extends Closeable, T extends Exception>
    {
        /**
         * constractor
         * @param clazz
         */
        public using(Class<T> clazz)
        {
            $(this, clazz);
        }

        /**
         * open
         * @return STREAM
         * @throws T
         */
        public abstract STREAM open() throws T;

        /**
         * handle
         * @param stream
         * @throws T
         */
        public abstract void handle(STREAM stream) throws T;

        /**
         * happen
         * @param exception
         */
        public abstract void happen(T exception);
    }

    @SuppressWarnings("unchecked")
    static <STREAM extends Closeable, T extends Exception> void $(
            using<STREAM, T> _, Class<T> clazz)
    {
        STREAM in = null;
        try
        {
            in = _.open();
            _.handle(in);
        }
        catch (Exception e)
        {
            if (clazz.isAssignableFrom(e.getClass()))
            {
                _.happen((T) e);
            }
            throw new RuntimeException(e);
        }
        finally
        {
            close(in);
        }
    }

    /**
     * @param c
     */
    static void close(Closeable c)
    {
        try
        {
            if (c != null)
            {
                c.close();
            }
        }
        catch (IOException e)
        {
            throw new RuntimeException(e);
        }
    }
}